package com.eric.study.reactor.commons.aspect;

import com.eric.study.reactor.commons.response.Response;
import com.eric.study.reactor.commons.response.ResponseError;
import com.eric.study.reactor.commons.response.ValidationError;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * <p> GlobalExceptionHandler.
 *
 * <p>
 * change history:
 *
 * <pre>
 * date         defect       person          comments
 * --------------------------------------------------------------------------------
 * 2023/9/20    ********     Qiheng Zhang    create file.
 * </pre>
 *
 * @author Qiheng Zhang
 * @date 2023/9/20 17:12
 * @copyright 2023, FA Software (Shanghai) Co., Ltd. All Rights Reserved.
 * @since 1.0.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(Exception.class)
    public Mono<Response> handlerException(Exception e, ServerWebExchange exchange) {
        log.error("[ExceptionHandler] error message: {}", e.getMessage());
        e.printStackTrace();
        return Mono.just(Response.failed().responseError(e.getMessage()));
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(WebExchangeBindException.class)
    public Mono<Response> handlerHibernateValidationException(WebExchangeBindException exception,
                                                              ServerWebExchange exchange) {
        final List<ValidationError> errorTemplates = exception.getFieldErrors().stream()
                .map(error -> new ValidationError(error.getObjectName(), error.getField(), error.getDefaultMessage()))
                .toList();
        return Mono.just(Response.failed().responseError(ResponseError.builder().system("Hibernate validation check " +
                "failed.").validation(errorTemplates).build()));
    }
}
